/*******************************************************************************
 * Copyright (c) 2000, 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
module dwt.browser.website;


private import dwt.dwt;


private import dwt.browser.browser;
private import dwt.browser.browserlisteners;
private import dwt.browser.browseradapters;;
private import dwt.browser.browserevents;


private import dwt.internal.ole.win32.com;
private import dwt.ole.win32.ole;
private import dwt.ole.win32.oleautomation;
private import dwt.ole.win32.olecontrolsite;
private import dwt.internal.ole.win32.OAIDL;
private import dwt.internal.ole.win32.OBJIDL;
private import dwt.internal.ole.win32.OLEIDL;
private import dwt.internal.ole.win32.DOCOBJ;
private import dwt.internal.ole.win32.extras;
private import dwt.internal.ole.win32.MSHTMHST;
private import dwt.internal.ole.win32.ifs;
private import dwt.widgets.composite;
private import dwt.widgets.event;
private import dwt.widgets.menu;
private import dwt.widgets.shell;
private import dwt.ole.win32.variant;




class _IDocHostUIHandlerImpl : IDocHostUIHandler {

	private import std.c.windows.windows;
	private import std.c.windows.com;

	WebSite parent;
	this(WebSite p) { parent = p; }
extern (Windows) :
	// interface of IUnknown
	HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
	ULONG AddRef()	{ return parent.AddRef(); }
	ULONG Release()	{ return parent.Release(); }

	// interface IDocHostUIHandler : IUnknown
	HRESULT ShowContextMenu( DWORD dwID, POINT* ppt, IUnknown pcmdtReserved, IDispatch pdispReserved){
		return parent.ShowContextMenu(dwID, ppt, pcmdtReserved, pdispReserved);
	}
	HRESULT GetHostInfo( DOCHOSTUIINFO * pInfo )	{ return COM.E_NOTIMPL; }
	HRESULT ShowUI( DWORD dwID, IOleInPlaceActiveObject pActiveObject, IOleCommandTarget pCommandTarget, IOleInPlaceFrame pFrame, IOleInPlaceUIWindow pDoc ){return COM.E_NOTIMPL;}
	HRESULT HideUI()	{return COM.E_NOTIMPL; }
	HRESULT UpdateUI()	{return COM.E_NOTIMPL; }
	HRESULT EnableModeless( BOOL fEnable )	{return COM.E_NOTIMPL; }
	HRESULT OnDocWindowActivate( BOOL fActivate )	{return COM.E_NOTIMPL; }
	HRESULT OnFrameWindowActivate( BOOL fActivate )	{return COM.E_NOTIMPL; }
	HRESULT ResizeBorder( LPRECT prcBorder, IOleInPlaceUIWindow pUIWindow, BOOL fRameWindow ){return COM.E_NOTIMPL; }
	HRESULT TranslateAccelerator( LPMSG lpMsg, GUID * pguidCmdGroup, DWORD nCmdID ){
		return parent.TranslateAccelerator(lpMsg, pguidCmdGroup, nCmdID );
	}
	HRESULT GetOptionKeyPath( LPOLESTR * pchKey, DWORD dw )	{return COM.E_NOTIMPL; }
	HRESULT GetDropTarget( IDropTarget pDropTarget, IDropTarget * ppDropTarget ) {return COM.E_NOTIMPL; }
	HRESULT GetExternal( IDispatch * ppDispatch )	{return COM.E_NOTIMPL; }
	HRESULT TranslateUrl( DWORD dwTranslate, OLECHAR * pchURLIn, OLECHAR ** ppchURLOut ){return COM.E_NOTIMPL; }
	HRESULT FilterDataObject( IDataObject pDO, IDataObject * ppDORet ) {return COM.E_NOTIMPL; }
}

class _IDocHostShowUIImpl : IDocHostShowUI {

	private import std.c.windows.windows;
	private import std.c.windows.com;


	WebSite parent;
	this(WebSite p) { parent = p; }
extern (Windows) :
	// interface of IUnknown
	HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
	ULONG AddRef()	{ return parent.AddRef(); }
	ULONG Release()	{ return parent.Release(); }

	// interface IDocHostShowUI : IUnknown
	HRESULT ShowMessage( HWND hwnd, LPOLESTR lpstrText, LPOLESTR lpstrCaption, DWORD dwType, LPOLESTR lpstrHelpFile, DWORD dwHelpContext, LRESULT * plResult){
		return parent.ShowMessage( hwnd, lpstrText, lpstrCaption, dwType, lpstrHelpFile, dwHelpContext, plResult);
	}
	/* Note.  One of the arguments of ShowHelp is a POINT struct and not a pointer to a POINT* struct. Because
	 * of the way Callback gets int parameters from a va_list of C arguments 2 integer arguments must be declared,
	 * ptMouse_x and ptMouse_y. Otherwise the Browser crashes when the user presses F1 to invoke
	 * the help.
	 */
	HRESULT ShowHelp( HWND hwnd, LPOLESTR pszHelpFile, UINT uCommand, DWORD dwData, POINT ptMouse, IDispatch pDispatchObjectHit ) {
		return COM.S_OK;
	}
}

class _IServiceProviderImpl : IServiceProvider {

	private import std.c.windows.windows;
	private import std.c.windows.com;


	WebSite parent;
	this(WebSite p) { parent = p; }
extern (Windows) :
	// interface of IUnknown
	HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
	ULONG AddRef()	{ return parent.AddRef(); }
	ULONG Release()	{ return parent.Release(); }

	// interface IServiceProvider : IUnknown
	HRESULT QueryService(REFGUID guidService, REFIID riid, void **ppv){
		return parent.QueryService(guidService, riid, ppv);
	}
}

// TODO:
/*
// <Shawn> I have problem to make this work, commented for temporarily

class _IInternetSecurityManagerImpl : IInternetSecurityManager {

	private import std.c.windows.windows;
	private import std.c.windows.com;


	WebSite parent;
	this(WebSite p) { parent = p; }
extern (Windows) :
	// interface of IUnknown
	HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
	ULONG AddRef()	{ return parent.AddRef(); }
	ULONG Release()	{ return parent.Release(); }

	// interface IInternetSecurityManager : IUnknown
	HRESULT SetSecuritySite(LPINTERNETSECURITYMGRSITE pSite) { return Browser.INET_E_DEFAULT_ACTION; }
	HRESULT GetSecuritySite(LPINTERNETSECURITYMGRSITE *ppSite) { return Browser.INET_E_DEFAULT_ACTION; }
	HRESULT MapUrlToZone(LPCWSTR pwszUrl, DWORD *pdwZone, DWORD dwFlags){
		return parent.MapUrlToZone(pwszUrl, pdwZone, dwFlags);
	}
	HRESULT GetSecurityId(LPCWSTR pwszUrl, BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved){
		return Browser.INET_E_DEFAULT_ACTION;
	}
	HRESULT ProcessUrlAction(LPCWSTR pwszUrl, DWORD dwAction, BYTE *pPolicy, DWORD cbPolicy, BYTE *pContext, DWORD cbContext, DWORD dwFlags, DWORD dwReserved){
		return COM.S_FALSE;
//		return parent.ProcessUrlAction(pwszUrl, dwAction, pPolicy, cbPolicy, pContext, cbContext, dwFlags, dwReserved);
	}
	HRESULT QueryCustomPolicy(LPCWSTR pwszUrl, REFGUID guidKey, BYTE **ppPolicy, DWORD *pcbPolicy, BYTE *pContext, DWORD cbContext, DWORD dwReserved){
		return Browser.INET_E_DEFAULT_ACTION;
	}
	HRESULT SetZoneMapping(DWORD dwZone, LPCWSTR lpszPattern, DWORD dwFlags) { return Browser.INET_E_DEFAULT_ACTION; }
	HRESULT GetZoneMappings(DWORD dwZone, LPENUMSTRING * ppenumString, DWORD dwFlags) { return COM.E_NOTIMPL; }
}

*/

class WebSite : OleControlSite {

	private import std.c.windows.windows;
	private import std.c.windows.com;


	_IDocHostUIHandlerImpl iDocHostUIHandler;
	_IDocHostShowUIImpl iDocHostShowUI;
	_IServiceProviderImpl iServiceProvider;
//	_IInternetSecurityManagerImpl iInternetSecurityManager;

public this(Composite parent, int style, char[] progId) {
	super(parent, style, progId);
}

protected void createCOMInterfaces () {
	super.createCOMInterfaces();

	iDocHostUIHandler = new _IDocHostUIHandlerImpl(this);
	iDocHostShowUI = new _IDocHostShowUIImpl(this);
	iServiceProvider = new _IServiceProviderImpl(this);
//	iInternetSecurityManager = new _IInternetSecurityManagerImpl(this);
}

package void disposeCOMInterfaces() {
	super.disposeCOMInterfaces();

	iDocHostUIHandler = null;
	iDocHostShowUI = null;
	iServiceProvider = null;
//	iInternetSecurityManager = null;
}

HRESULT QueryInterface(REFIID riid, void ** ppvObject) {
	int result = super.QueryInterface(riid, ppvObject);
	if (result == COM.S_OK) return result;
	if (riid is null || ppvObject is null) return COM.E_INVALIDARG;

	if (COM.IsEqualGUID(riid, &COM.IIDIDocHostUIHandler)) {
		*ppvObject = cast(void*)(cast(IDocHostUIHandler)iDocHostUIHandler);
		AddRef();
		return COM.S_OK;
	}
	if (COM.IsEqualGUID(riid, &COM.IIDIDocHostShowUI)) {
		*ppvObject = cast(void*)(cast(IDocHostShowUI)iDocHostShowUI);
		AddRef();
		return COM.S_OK;
	}
	if (COM.IsEqualGUID(riid, &COM.IIDIServiceProvider)) {
		*ppvObject = cast(void*)(cast(IServiceProvider)iServiceProvider);
		AddRef();
		return COM.S_OK;
	}
// TODO: <Shawn> I have problem to make IInternetSecurityManager interface work,
// commented for temporarily
//	if (COM.IsEqualGUID(riid, &COM.IIDIInternetSecurityManager)) {
//		*ppvObject = cast(IInternetSecurityManager)iInternetSecurityManager;
//		AddRef();
//		return COM.S_OK;
//	}
	*ppvObject = null;
	return COM.E_NOINTERFACE;
}

/* IDocHostUIHandler */

HRESULT ShowContextMenu( DWORD dwID, POINT* ppt, IUnknown pcmdtReserved, IDispatch pdispReserved) {
	Browser browser = cast(Browser)(getParent().getParent());
	Event event = new Event();
	event.x = ppt.x;
	event.y = ppt.y;
	browser.notifyListeners(DWT.MenuDetect, event);
	if (!event.doit) return COM.S_OK;
	Menu menu = browser.getMenu();
	if (menu !is null && !menu.isDisposed ()) {
		if (ppt.x != event.x || ppt.y != event.y) {
			menu.setLocation (event.x, event.y);
		}
		menu.setVisible (true);
		return COM.S_OK;
	}
	/* Show default IE popup menu */
	return COM.S_FALSE;
}

HRESULT TranslateAccelerator( LPMSG lpMsg, GUID * pguidCmdGroup, DWORD nCmdID ) {
	/*
	* Feature on Internet Explorer.  By default the embedded Internet Explorer control runs
	* the Internet Explorer shortcuts (e.g. F5 for refresh).  This overrides the shortcuts
	* defined by DWT.  The workaround is to forward the accelerator keys to the parent window
	* and have Internet Explorer ignore the ones handled by the parent window.
	*/
	Menu menubar = getShell().getMenuBar();
	if (menubar !is null && !menubar.isDisposed() && menubar.isEnabled()) {
		Shell shell = menubar.getShell();
		HWND hwnd = shell.handle;
		HACCEL hAccel = cast(HACCEL)OS.SendMessage(hwnd, OS.WM_APP+1, 0, 0);
		if (hAccel !is null) {
			if (OS.TranslateAccelerator(hwnd, hAccel, lpMsg) != 0) return COM.S_OK;
		}
	}
	/*
	* Feature on Internet Explorer.  By default the embedded Internet Explorer control runs
	* the Internet Explorer shortcuts. F5 causes refresh).  This behaviour is undesired when
	* rendering HTML in memory as it causes the empty page about:blank page to be reloaded.
	* The workaround is to block the default F5 handling by IE when the URL is about:blank.
	*/
	OleAutomation automation = new OleAutomation(this);
	char[][] StringArr;
	StringArr ~= "LocationURL";
	int[] rgdispid = automation.getIDsOfNames(StringArr); //$NON-NLS-1$
	Variant pVarResult = automation.getProperty(rgdispid[0]);
	automation.dispose();
	int result = COM.S_FALSE;
	if (pVarResult !is null) {
		if (pVarResult.getType() == OLE.VT_BSTR) {
			char[] url = pVarResult.getString();
			if (url == (Browser.ABOUT_BLANK)) {
				if (lpMsg.message == OS.WM_KEYDOWN && lpMsg.wParam == OS.VK_F5) result = COM.S_OK;
			}
		}
		pVarResult.dispose();
	}
	return result;
}

/* IDocHostShowUI */

HRESULT ShowMessage( HWND hwnd, LPOLESTR lpstrText, LPOLESTR lpstrCaption, DWORD dwType, LPOLESTR lpstrHelpFile, DWORD dwHelpContext, LRESULT * plResult) {
	/*
	* Feature on IE.  Executing certain ActiveX controls such as the Java or Flash plugin from within
	* a java VM can cause the application to crash.  The workaround is to disallow all ActiveX controls.
	*
	* Feature on IE.  When IE navigates to a website that contains an ActiveX that is prevented from
	* being executed, IE displays a message "Your current security settings prohibit running ActiveX
	* controls on this page ...".  The workaround is to selectively block this alert as indicated
	* in the MSDN article "WebBrowser customization".
	*/
	/* resource identifier in shdoclc.dll for window caption "Your current security settings prohibit
	 * running ActiveX controls on this page ..."
	 */
	int IDS_MESSAGE_BOX_CAPTION = 8033;
		if (lpstrText !is null) {
		HINSTANCE hModule = OS.LoadLibrary("SHDOCLC.DLL\0");
		if (hModule !is null) {
			/*
			* Note.  lpstrText is a LPOLESTR, i.e. a null terminated unicode string LPWSTR, i.e. a WCHAR*.
			* It is not a BSTR.  A BSTR is a null terminated unicode string that contains its length
			* at the beginning.
			*/
			int cnt = OS.wcslen(lpstrText);
			/*
			* Note.  lpstrText is unicode on both unicode and ansi platforms.
			* The nbr of chars is multiplied by the constant 2 and not by TCHAR.sizeof since
			* TCHAR.sizeof returns 1 on ansi platforms.
			*/
			char[] text = Converter.WCHARzToStr(lpstrText, cnt);
			/* provide a buffer large enough to hold the string to compare to and a null terminated character */
			int length = OS.IsUnicode ? cnt : text.length;

			TCHAR[] lpBuffer = new TCHAR[length+1];
			int result = OS.LoadString(hModule, IDS_MESSAGE_BOX_CAPTION, lpBuffer.ptr, length);
			OS.FreeLibrary(hModule);
			return result > 0 && (text == (Converter.TCHARzToStr(lpBuffer.ptr, result)))? COM.S_OK : COM.S_FALSE;
		}
	}
	return COM.S_FALSE;
}


/* IServiceProvider */

HRESULT QueryService(REFGUID guidService, REFIID riid, void **ppv) {
	if (riid is null || ppv is null) return COM.E_INVALIDARG;

// TODO: <Shawn> I have problem to make IInternetSecurityManager interface work,
// commented for temporarily
//	if (*riid == COM.IIDIInternetSecurityManager) {
//		*ppv = iInternetSecurityManager;
//		AddRef();
//		return COM.S_OK;
//	}
	*ppv = null;
	return COM.E_NOINTERFACE;
}


// TODO: <Shawn> I have problem to make IInternetSecurityManager interface work,
// commented for temporarily
/+
// IInternetSecurityManager interface
HRESULT MapUrlToZone(LPCWSTR pwszUrl, DWORD *pdwZone, DWORD dwFlags) {
	if(pwszUrl is null || pdwZone is null)
		return COM.E_INVALIDARG;
	/*
	* Note.  pwszUrl is unicode on both unicode and ansi platforms.
	* The nbr of chars is multiplied by the constant 2 and not by TCHAR.sizeof since
	* TCHAR.sizeof returns 1 on ansi platforms.
	*/
	char[] url = Converter.WCHARzToStr(pwszUrl, -1);

	/*
	* Feature in IE 6 sp1.  HTML rendered in memory
	* does not enable local links but the exact same
	* HTML document loaded through a local file is
	* permitted to follow local links.  The workaround is
	* to return URLZONE_INTRANET instead of the default
	* value URLZONE_LOCAL_MACHINE.
	*/
	int zone = Browser.URLZONE_INTRANET;

	/*
	* Note.  Some ActiveX plugins crash when executing
	* inside the embedded explorer itself running into
	* a JVM.  The current workaround is to detect when
	* such ActiveX is about to be started and refuse
	* to execute it.
	* ActiveX blocked in an object tag:
	* - Shockwave director plugin (mime: application/x-director)
	* - Java plugin
	*/

	if (url.indexOf(Browser.URL_DIRECTOR) == 0 ||
		(url.indexOf(Browser.URL_JAVA) == 0 && url.indexOf(Browser.URL_CAB) != -1) ||
		(url.indexOf(Browser.URL_JAVA_15) == 0 && url.indexOf(Browser.URL_CAB) != -1)) {
		zone = Browser.URLZONE_LOCAL_MACHINE;
	}
	*pdwZone = zone;
	return COM.S_OK;
}

HRESULT ProcessUrlAction(LPCWSTR pwszUrl, DWORD dwAction, BYTE *pPolicy, DWORD cbPolicy, BYTE *pContext, DWORD cbContext, DWORD dwFlags, DWORD dwReserved) {
	/*
	* Feature in IE 6 sp1.  HTML rendered in memory
	* containing an OBJECT tag referring to a local file
	* brings up a warning dialog asking the user whether
	* it should proceed or not.  The workaround is to
	* set the policy to URLPOLICY_ALLOW in this case (dwAction
	* value of 0x1406).
	*
	* Feature in IE. Security Patches and user settings
	* affect the way the embedded web control behaves.  The current
	* approach is to consider the content trusted and allow
	* all URLs by default.
	*/
	int policy = Browser.URLPOLICY_ALLOW;
	/*
	* Note. The URLACTION_JAVA flags refer to the applet tag that normally resolve to
	* the Microsoft VM, not to the java OBJECT tag that resolves to the
	* Sun plugin. Return URLPOLICY_JAVA_LOW to authorize applets instead of
	* URLPOLICY_ALLOW that is interpreted as URLPOLICY_JAVA_PROHIBIT in this
	* context.
	*/
	if (dwAction >= Browser.URLACTION_JAVA_MIN && dwAction <= Browser.URLACTION_JAVA_MAX) {
		policy = Browser.URLPOLICY_JAVA_LOW;
	}
	if (dwAction >= Browser.URLACTION_ACTIVEX_MIN && dwAction <= Browser.URLACTION_ACTIVEX_MAX) {
		/*
		* Note.  pwszUrl is unicode on both unicode and ansi platforms.
		* The nbr of chars is multiplied by the constant 2 and not by TCHAR.sizeof since
		* TCHAR.sizeof returns 1 on ansi platforms.
		*/
		char[] url = Converter.WCHARzToStr(pwszUrl, -1);
		/*
		* Note.  Some ActiveX plugins crash when executing
		* inside the embedded explorer itself running into
		* a JVM.  The current workaround is to detect when
		* such ActiveX is about to be started and refuse
		* to execute it.
		* ActiveX blocked based on URL extension:
		* - Shockwave director plugin (mime: application/x-director)
		*/
		if (Converter.indexOf(url, ".dcr") == url.length - 4) policy = Browser.URLPOLICY_DISALLOW; //$NON-NLS-1$
	}
	if (cbPolicy >= 4)
		*pPolicy = cast(BYTE)policy;
	return COM.S_OK;
}
+/

}
